#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    tcpsocket = new QTcpSocket;
    qdir.setCurrent(".");
    connect(tcpsocket, SIGNAL(connected()), this, SLOT(success_connect()));
    connect(ui->listWidget_server, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(server_double_clicked()));
    connect(ui->listWidget_client, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(client_double_clicked()));
}

Widget::~Widget()
{
    delete tcpsocket;
    delete pasv_socket;
    delete ui;
}

void Widget::on_pushButton_connect_clicked()
{
    tcpsocket->connectToHost(ui->lineEdit_serverip->text(), 21);
    if(!tcpsocket->waitForConnected(3000))
    {
        QMessageBox::information(this, "Error", "Fail Connect");
    }
}

void Widget::on_pushButton_put_clicked()
{
    pasv_socket = pasv();
    std::string stor = "STOR " + ui->listWidget_client->currentItem()->text().toStdString() + "\n";
    tcpsocket->write(stor.c_str(), stor.size());
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }

    std::string file_dir = qdir.absolutePath().toStdString() + "/" + ui->listWidget_client->currentItem()->text().toStdString();
    std::fstream fr(file_dir.c_str(), std::ios::in | std::ios::binary);
    if(!fr.is_open())
    {
        qDebug("open error");
        return;
    }
    int ret = 0;
    char read_buf[1024] = {};
    while(fr.read(read_buf, 1))
    {
        pasv_socket->write(read_buf, 1);
        pasv_socket->waitForBytesWritten();
    }
    fr.close();
    pasv_socket->close();
    recv();
    list();
}

void Widget::on_pushButton_get_clicked()
{
    pasv_socket = pasv();

    std::string retr = "RETR " + ui->listWidget_server->currentItem()->text().toStdString() + "\n";

    tcpsocket->write(retr.c_str(), retr.size());
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }
    std::string file_dir = qdir.absolutePath().toStdString() + "/" + ui->listWidget_server->currentItem()->text().toStdString();
    qDebug(file_dir.c_str());
    std::fstream fw(file_dir.c_str(), std::ios::out | std::ios::binary);
    int ret = 0;
    char read_buf[1024] = {};

    while(true)
    {
        pasv_socket->waitForReadyRead();
        ret = pasv_socket->read(read_buf, 1024);
        fw.write(read_buf, ret);
        if(ret < 1024) break;
    }

    fw.close();
    pasv_socket->close();
    recv();

    list_cilent();
}

void Widget::server_double_clicked()
{
    std::string cwd_dir = "CWD " + ui->listWidget_server->currentItem()->text().toStdString() + "\n";
    tcpsocket->write(cwd_dir.c_str(), cwd_dir.size());
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }
    list();
}

void Widget::client_double_clicked()
{
    qDebug(ui->listWidget_client->currentItem()->text().toStdString().c_str());
    qdir.cd(ui->listWidget_client->currentItem()->text());
    list_cilent();
}

void Widget::success_connect()
{
    std::string name = "USER " + ui->lineEdit_username->text().toStdString() + "\n";
    tcpsocket->write(name.c_str(), name.size());
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }

    std::string pass = "PASS " + ui->lineEdit_password->text().toStdString() + "\n";
    tcpsocket->write(pass.c_str(), pass.size());
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }

    list();
    list_cilent();
}

void Widget::list()
{
    tcpsocket->write("PWD\n", 4);
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }
    std::string temp(buf+5, strchr(buf, '\n')-2);
    ui->lineEdit_serverdir->setText(temp.c_str());

    ui->listWidget_server->clear();
    pasv_socket = pasv();
    tcpsocket->write("LIST -al\n", 9);
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }
    pasv_recv();
    pasv_socket->close();

    char* p = buf;
    QList<QListWidgetItem*> aitemlist;

    while(strchr(p , '\n'))
    {
        std::string temp;
        temp.assign(p, strchr(p , '\n')-1);

        QListWidgetItem* aitem = new QListWidgetItem(QIcon(), temp.c_str()+56);
        aitemlist.push_back(aitem);
        if(temp[0] == 'd')
        {
            aitem->setIcon(QIcon("image/dir.png"));
        }
        else
        {
            aitem->setIcon(QIcon("image/file.png"));
        }
        ui->listWidget_server->addItem(aitem);
        p = strchr(p, '\n')+1;
    }
}

void Widget::list_cilent()
{
    qdir.cd(qdir.absolutePath());
    ui->lineEdit_clientdir->setText(qdir.absolutePath());
    ui->listWidget_client->clear();
    QFileInfoList qfileinfolist;
    qfileinfolist = qdir.entryInfoList();


    QList<QListWidgetItem*> aitemlist;
    for(int i=0; i<qfileinfolist.size(); i++)
    {
        QListWidgetItem* aitem = new QListWidgetItem(QIcon(), qfileinfolist.at(i).fileName());
        aitemlist.push_back(aitem);
        if(qfileinfolist.at(i).isDir())
        {
            aitem->setIcon(QIcon("image/dir.png"));
        }
        else
        {
            aitem->setIcon(QIcon("image/file.png"));
        }
        ui->listWidget_client->addItem(aitem);
    }
}

void Widget::recv()
{
    bzero(buf, 4096);
    if(tcpsocket->waitForReadyRead())
    {
        tcpsocket->read(buf, sizeof(buf));
    }
    qDebug(buf);
}

void Widget::pasv_recv()
{
    bzero(buf, 4096);
    if(pasv_socket->waitForReadyRead())
    {
        while(pasv_socket->read(buf, sizeof(buf)));
    }
    qDebug(buf);
}

QTcpSocket* Widget::pasv()
{
    tcpsocket->write("PASV\n", 5);
    if(tcpsocket->waitForBytesWritten())
    {
        recv();
    }
    unsigned char ip1, ip2, ip3, ip4, port1, port2;
    sscanf(strchr(buf, '(')+1, "%hhu, %hhu, %hhu, %hhu, %hhu, %hhu", &ip1, &ip2, &ip3, &ip4, &port1, &port2);
    sprintf(buf, "%hhu.%hhu.%hhu.%hhu", ip1, ip2, ip3, ip4);
    QTcpSocket* socket = new QTcpSocket;
    socket->connectToHost(buf, port1*256+port2);
    return socket;
}
